/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.moderatorplugin;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.Serializable;
import java.util.List;

import javax.swing.*;

import com.pearreview.ui.*;
import com.pearreview.ui.slidebox.AttendeeSlideBoxPanel;
import com.pearreview.ui.slidebox.SlideBoxPanel;
import com.pearreview.application.Messages;
import com.pearreview.util.review.Attendee;
import com.pearreview.util.review.AttendeeRole;
import com.pearreview.util.review.IdArrayList;
import com.pearreview.util.review.IdList;

/**
 * This class creates a container with components for 
 * managing creating, showing and editing attendees of the review.
 *
 */
public class AttendeePanel extends PearPanel implements ModeratorPanel {
	private static final long serialVersionUID = -4318115286883094930L;
	
	private FormLabel attendeeNameLabel;
	private CompletableJTextField attendeeName;
	private FormLabel attendeeContactLabel;
	private CompletableJTextField attendeeContact;
	private FormLabel attendeeRoleLabel;
	private JComboBox attendeeRole;
	private JButton addAttendeeBtn;
	private AttendeeSlideBoxPanel slideList;
	private SlideBoxPanel.RemoveConfirmer removeConfirmer = 
			new RemoveConfirmer();
	private JPanel newFormPanel;
	private JPanel editFormPanel;
	private JPanel formPanel;
	private GroupLayout layout;
	private FormLabel editAttendeeNameLabel;
	private CompletableJTextField editAttendeeName;
	private FormLabel editAttendeeContactLabel;
	private CompletableJTextField editAttendeeContact;
	private FormLabel editAttendeeRoleLabel;
	private JComboBox editAttendeeRole;
	private JButton editAttendeeBtn;
	private JButton abortEditBtn;
	private EditAttendeeAction editAction = new EditAttendeeAction();
	private HeadingLabel headingLabel;
	private Attendee editAttendee;
	
	private String[] attendeeRoles = { 
			Messages.getString("PearReview.review.modarator"),
			Messages.getString("PearReview.review.scribe"),
			Messages.getString("PearReview.review.reviewer"),
			Messages.getString("PearReview.review.author"),
			Messages.getString("PearReview.review.customer")};
	
	private int[] createCounter = new int[attendeeRoles.length];
	
	private BottomButtonPanel bottom;
	
	public AttendeePanel() {
		initComponents();
	}
	
	public AttendeePanel(List<Attendee> attendees) {
		this();
		setAttendees(attendees);
	}
	
	/**
	 * Sets list of attendees
	 * @param attendees attendees to set
	 */
	public void setAttendees(List<Attendee> attendees) {
		slideList.clearList();
		
		if(attendees != null)
			slideList.setElements(attendees);
	}
	
	/**
	 * Returns list of attendees
	 * @return attendees
	 */
	public IdList<Attendee> getAttendees() {
		int count = slideList.getListSize();
		
		IdList<Attendee> lst = new IdArrayList<Attendee>();
		
		for(int i = 0 ; i < count ; i++) {
			Attendee attendee = slideList.getListElement(i);
			
			if(attendee.getName() == null)
				attendee.setName("");
			
			if(attendee.getContact() == null)
				attendee.setContact("");
			
			lst.add(attendee);
		}
		
		lst.regenerateIds();
		
		return lst;
	}
	
	@Override
	public boolean isValidForm() {
		return slideList.getListSize() > 0;
	}
	
	/**
	 * Returns attendee slide box panel, where contains the attendees
	 * @return attendee slide box panel
	 */
	public AttendeeSlideBoxPanel getAttendeeSlideBoxPanel() {
		return slideList;
	}

	/**
	 * Initializes components
	 */
	private void initComponents() {
		
		attendeeNameLabel = new FormLabel(Messages.getString(
				"PearReview.Moderator.attendees.name"));
		attendeeName = new CompletableJTextField();
		attendeeContactLabel = new FormLabel(Messages.getString(
				"PearReview.Moderator.attendees.contact"));
		attendeeContact = new CompletableJTextField();
		attendeeRoleLabel = new FormLabel(Messages.getString(
				"PearReview.Moderator.attendees.role"));
		attendeeRole = new JComboBox(attendeeRoles);
		addAttendeeBtn = new JButton();
		
		editAttendeeNameLabel = new FormLabel(Messages.getString(
				"PearReview.Moderator.attendees.name"));
		editAttendeeName = new CompletableJTextField();
		editAttendeeContactLabel = new FormLabel(Messages.getString(
				"PearReview.Moderator.attendees.contact"));
		editAttendeeContact = new CompletableJTextField();
		editAttendeeRoleLabel = new FormLabel(Messages.getString(
			"PearReview.Moderator.attendees.role"));
		editAttendeeRole = new JComboBox(attendeeRoles);
		editAttendeeBtn = new JButton();
		abortEditBtn = new JButton();

		this.setLayout(new BorderLayout());
		this.setPreferredSize(new Dimension(680,400));
		
		setBackground(new Color(214, 214, 214));
		
		
		//======== addAttendeeBtn ========
		addAttendeeBtn.setAction(new AddNewAttendeeAction());
		addAttendeeBtn.setFont(new Font("Tahoma",Font.PLAIN, 12));
		addAttendeeBtn.setText(Messages.getString(
				"PearReview.Moderator.add_btn"));
		
		//======== attendeeRole ========
		attendeeRole.setFont(new Font("Tahoma",Font.PLAIN, 12));
		if (System.getProperty("os.name").equals("Mac OS X")) {
			attendeeRole.setBorder(BorderFactory.createEmptyBorder(
					0, 0, 0, 0));
		} else {
			attendeeRole.setBorder(BorderFactory.createMatteBorder(
							1, 1, 1, 1, new Color(0x828790)));
		}
		
		
		//======== slideList ========
		slideList = new AttendeeSlideBoxPanel(editAction);
		slideList.setRemoveConfirmer(removeConfirmer);
		
		
		//======== newFormPanel ========
		newFormPanel = new JPanel();
		newFormPanel.setOpaque(false);
		GroupLayout layoutNewForm = new GroupLayout(newFormPanel);
		newFormPanel.setLayout(layoutNewForm);
		
		layoutNewForm.setHorizontalGroup(layoutNewForm.createSequentialGroup()
				.addContainerGap()
				.addGroup(layoutNewForm.createParallelGroup()
						.addGroup(layoutNewForm.createSequentialGroup()
								.addGroup(layoutNewForm.createParallelGroup()
									.addGroup(GroupLayout.Alignment.TRAILING, 
											layoutNewForm
											.createSequentialGroup()
										.addGroup(
												layoutNewForm
												.createParallelGroup()
											.addComponent(attendeeNameLabel, 
													GroupLayout.Alignment
													.LEADING, 
													GroupLayout.DEFAULT_SIZE, 
													80, 
													GroupLayout.PREFERRED_SIZE)
											.addComponent(attendeeContactLabel,
													GroupLayout.Alignment
													.LEADING, 
													GroupLayout.DEFAULT_SIZE, 
													80, 
													GroupLayout.PREFERRED_SIZE)
											.addComponent(attendeeRoleLabel,
													GroupLayout.Alignment
													.LEADING, 
													GroupLayout.DEFAULT_SIZE, 
													80, 
													GroupLayout.PREFERRED_SIZE)
													)
										.addGap(57, 57, 57)
										.addGroup(
												layoutNewForm
												.createParallelGroup(
														GroupLayout.Alignment
														.TRAILING)
											.addComponent(addAttendeeBtn, 
													GroupLayout.Alignment
													.LEADING, 
													GroupLayout.DEFAULT_SIZE, 
													GroupLayout.PREFERRED_SIZE, 
													GroupLayout.PREFERRED_SIZE)
											.addComponent(attendeeRole, 
													GroupLayout.Alignment
													.LEADING, 
													GroupLayout.DEFAULT_SIZE, 
													300, 
													GroupLayout.PREFERRED_SIZE)
											.addComponent(attendeeContact, 
													GroupLayout.Alignment
													.LEADING, 
													GroupLayout.DEFAULT_SIZE, 
													300, 
													GroupLayout.PREFERRED_SIZE)
											.addComponent(attendeeName, 
													GroupLayout.Alignment
													.LEADING, 
													GroupLayout.DEFAULT_SIZE, 
													300, 
													GroupLayout.PREFERRED_SIZE)
													)
										))))
		);
		
		layoutNewForm.setVerticalGroup(
						layoutNewForm.createSequentialGroup()
						.addContainerGap()
						.addGroup(layoutNewForm.createParallelGroup(
								GroupLayout.Alignment.BASELINE)
							.addComponent(attendeeNameLabel)
							.addComponent(attendeeName, 
									GroupLayout.PREFERRED_SIZE, 
									GroupLayout.DEFAULT_SIZE, 
									GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(
								LayoutStyle.ComponentPlacement.UNRELATED)
						.addGroup(layoutNewForm.createParallelGroup()
							.addComponent(attendeeContactLabel)
							.addComponent(attendeeContact, 
									GroupLayout.PREFERRED_SIZE, 
									GroupLayout.DEFAULT_SIZE, 
									GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(
								LayoutStyle.ComponentPlacement.UNRELATED)
						.addGroup(layoutNewForm.createParallelGroup()
							.addComponent(attendeeRoleLabel)
							.addComponent(attendeeRole, 
									GroupLayout.PREFERRED_SIZE, 
									GroupLayout.DEFAULT_SIZE, 
									GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(
								LayoutStyle.ComponentPlacement.UNRELATED)
						.addGroup(layoutNewForm.createParallelGroup()
							.addComponent(addAttendeeBtn))
		);
		
		
		//======== editFormPanel ========
		editFormPanel = new JPanel();
		editFormPanel.setOpaque(false);
		//editFormPanel.setBorder(BorderFactory.createMatteBorder(
		//		1, 1, 1, 1, new Color(0x828790)));
		
		//======== editAttendeeRole ========
		editAttendeeRole.setFont(new Font("Tahoma",Font.PLAIN, 12));
		if (System.getProperty("os.name").equals("Mac OS X")) {
			editAttendeeRole.setBorder(BorderFactory.createEmptyBorder(
					0, 0, 0, 0));
		} else {
			editAttendeeRole.setBorder(BorderFactory.createMatteBorder(
							1, 1, 1, 1, new Color(0x828790)));
		}
		
		
		//======== editAttendeeBtn ========
		editAttendeeBtn.setAction(new EndEditAttendeeAction());
		editAttendeeBtn.setFont(new Font("Tahoma",Font.PLAIN, 12));
		editAttendeeBtn.setText(Messages.getString(
				"PearReview.Moderator.attendees.save"));
		
		//======== abortEditBtn ========
		abortEditBtn.setAction(new AbortEditAttendeeAction());
		abortEditBtn.setFont(new Font("Tahoma",Font.PLAIN, 12));
		abortEditBtn.setText(Messages.getString(
				"PearReview.Moderator.attendees.abort"));
		
		GroupLayout layoutEditForm = new GroupLayout(editFormPanel);
		editFormPanel.setLayout(layoutEditForm);
		
		layoutEditForm.setHorizontalGroup(
				layoutEditForm.createSequentialGroup()
				.addContainerGap()
				.addGroup(layoutEditForm.createParallelGroup()
						.addGroup(layoutEditForm.createSequentialGroup()
								.addGroup(layoutEditForm.createParallelGroup()
									.addGroup(
											GroupLayout.Alignment.TRAILING, 
											layoutEditForm
											.createSequentialGroup()
										.addGroup(
												layoutEditForm
												.createParallelGroup()
										.addComponent(
												editAttendeeNameLabel, 
												GroupLayout.Alignment.LEADING, 
												GroupLayout.DEFAULT_SIZE, 
												80, 
												GroupLayout.PREFERRED_SIZE)
										.addComponent(
												editAttendeeContactLabel,
												GroupLayout.Alignment.LEADING, 
												GroupLayout.DEFAULT_SIZE, 
												80, 
												GroupLayout.PREFERRED_SIZE)
										.addComponent(
												editAttendeeRoleLabel,
												GroupLayout.Alignment.LEADING, 
												GroupLayout.DEFAULT_SIZE, 
												80, 
												GroupLayout.PREFERRED_SIZE))
									.addGap(57, 57, 57)
									.addGroup(
										layoutEditForm.createParallelGroup(
												GroupLayout.Alignment.LEADING)
										.addGroup(
												layoutEditForm
												.createSequentialGroup()
												.addComponent(editAttendeeBtn)
												.addGap(10, 10, 10)
												.addComponent(abortEditBtn))
										.addComponent(editAttendeeRole, 
												GroupLayout.Alignment.LEADING, 
												GroupLayout.DEFAULT_SIZE, 
												300, 
												GroupLayout.PREFERRED_SIZE)
										.addComponent(
												editAttendeeContact, 
												GroupLayout.Alignment.LEADING, 
												GroupLayout.DEFAULT_SIZE, 
												300, 
												GroupLayout.PREFERRED_SIZE)
										.addComponent(editAttendeeName, 
												GroupLayout.Alignment.LEADING, 
												GroupLayout.DEFAULT_SIZE, 
												300, 
												GroupLayout.PREFERRED_SIZE))
										))))
		);
		
		layoutEditForm.setVerticalGroup(
						layoutEditForm.createSequentialGroup()
						.addContainerGap()
						.addGroup(layoutEditForm.createParallelGroup(
								GroupLayout.Alignment.BASELINE)
							.addComponent(editAttendeeNameLabel)
							.addComponent(editAttendeeName, 
									GroupLayout.PREFERRED_SIZE, 
									GroupLayout.DEFAULT_SIZE, 
									GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(
								LayoutStyle.ComponentPlacement.UNRELATED)
						.addGroup(layoutEditForm.createParallelGroup()
							.addComponent(editAttendeeContactLabel)
							.addComponent(editAttendeeContact, 
									GroupLayout.PREFERRED_SIZE, 
									GroupLayout.DEFAULT_SIZE, 
									GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(
								LayoutStyle.ComponentPlacement.UNRELATED)
						.addGroup(layoutEditForm.createParallelGroup()
							.addComponent(editAttendeeRoleLabel)
							.addComponent(editAttendeeRole, 
									GroupLayout.PREFERRED_SIZE, 
									GroupLayout.DEFAULT_SIZE, 
									GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(
								LayoutStyle.ComponentPlacement.UNRELATED)
						.addGroup(layoutEditForm.createParallelGroup()
							.addComponent(editAttendeeBtn)
							.addComponent(abortEditBtn))
		);

		//======== formPanel ========
		formPanel = new JPanel();
		formPanel.setOpaque(false);
		
		layout = new GroupLayout(formPanel);
		
		initFormPanel(newFormPanel);
		
		formPanel.setPreferredSize(new Dimension(300, 300));
		add(formPanel, BorderLayout.CENTER);
		headingLabel = new HeadingLabel(
				Messages.getString("PearReview.Scribe.tabs.attendees"));
		add(headingLabel, BorderLayout.NORTH);
		
		bottom = new BottomButtonPanel();
		add(bottom, BorderLayout.SOUTH);
	}
	
	private void initFormPanel(JPanel currentFormPanel) {
		formPanel.removeAll();
		formPanel.setLayout(layout);
		layout.setHorizontalGroup(
			layout.createParallelGroup()
				.addGroup(layout.createSequentialGroup()
					.addGroup(layout.createParallelGroup()
						.addGroup(layout.createSequentialGroup()
							.addGroup(layout.createParallelGroup()
								.addGroup(
										GroupLayout.Alignment.TRAILING, 
										layout.createSequentialGroup()
									.addGroup(layout.createParallelGroup()
											.addComponent(currentFormPanel))
									.addGap(37, 37, 37)
									.addGroup(layout.createParallelGroup(
											GroupLayout.Alignment.TRAILING)
											.addComponent(slideList, 
													GroupLayout.PREFERRED_SIZE, 
													GroupLayout.DEFAULT_SIZE, 
													Short.MAX_VALUE))
									.addGap(10, 10, 10)
		))))));
		
		layout.setVerticalGroup(
			layout.createParallelGroup()
				.addGroup(layout.createSequentialGroup()
						.addComponent(currentFormPanel))
					.addGroup(layout.createSequentialGroup()
							.addContainerGap()
							.addComponent(slideList)
							.addContainerGap())
		);
	}
	
	/**
	 * Reads the current information from the input 'new Attendee' fields,
	 * resets the form and returns the data as Attendee object.
	 * 
	 * @return
	 */
	private Attendee getAttendeeNewForm() {
		Attendee attendee = new Attendee();
		
		//read from field, add auto completion and reset the field
		attendee.setName(attendeeName.getText());
		attendeeName.addCompletion(attendeeName.getText());
		editAttendeeName.addCompletion(attendeeName.getText());
		attendeeName.setText(null);
		
		attendee.setContact(attendeeContact.getText());
		attendeeContact.addCompletion(attendeeContact.getText());
		editAttendeeContact.addCompletion(attendeeContact.getText());
		attendeeContact.setText(null);
		
		switch (this.attendeeRole.getSelectedIndex()) {
			case 0: 
				attendee.setRole(AttendeeRole.Moderator);
				break;
				
			case 1: 
				attendee.setRole(AttendeeRole.Scribe);
				break;
				
			case 2: 
				attendee.setRole(AttendeeRole.Reviewer);
				break;
				
			case 3: 
				attendee.setRole(AttendeeRole.Author);
				break;
				
			case 4: 
				attendee.setRole(AttendeeRole.Customer);
				break;
				
			default:
				attendee.setRole(AttendeeRole.Moderator);
				break;
		}
		
		if(attendee.getName() == null || attendee.getName().equals("")) {
			int index = attendeeRole.getSelectedIndex();
			createCounter[index] ++;
			String role = attendeeRoles[index];
			attendee.setName(role + " " + createCounter[index]);
		}
		
		return attendee;
	}
	
	/**
	 * Reads the current information from the 'edit Attendee' form.
	 * 
	 * @return
	 */
	private Attendee getAttendeeEditForm() {
		Attendee attendee = editAttendee;
		
		//read from field, add auto completion and reset the field
		attendee.setName(editAttendeeName.getText());
		editAttendeeName.addCompletion(editAttendeeName.getText());
		attendeeName.addCompletion(editAttendeeName.getText());
		editAttendeeName.setText(null);
		
		attendee.setContact(editAttendeeContact.getText());
		editAttendeeContact.addCompletion(editAttendeeContact.getText());
		attendeeContact.addCompletion(editAttendeeContact.getText());
		editAttendeeContact.setText(null);
		
		switch (editAttendeeRole.getSelectedIndex()) {
			case 0: 
				attendee.setRole(AttendeeRole.Moderator);
				break;
				
			case 1: 
				attendee.setRole(AttendeeRole.Scribe);
				break;
				
			case 2: 
				attendee.setRole(AttendeeRole.Reviewer);
				break;
				
			case 3: 
				attendee.setRole(AttendeeRole.Author);
				break;
				
			case 4: 
				attendee.setRole(AttendeeRole.Customer);
				break;
				
			default:
				attendee.setRole(AttendeeRole.Moderator);
				break;
		}
		
		return attendee;
	}
	
	/**
	 * Fills the information into the edit form.
	 * 
	 * @param attendee
	 */
	private void setEditForm(Attendee attendee) {
		
		//reset all fields
		this.editAttendeeName.setText(null);
		this.editAttendeeContact.setText(null);
		this.editAttendeeRole.setSelectedIndex(0);
		
		//set fields
		this.editAttendeeName.setText(attendee.getName());
		this.editAttendeeContact.setText(attendee.getContact());
		
		switch (attendee.getRole()) {
		case Moderator:
			this.editAttendeeRole.setSelectedIndex(0);
			break;
		
		case Scribe:
			this.editAttendeeRole.setSelectedIndex(1);
			break;
			
		case Reviewer:
			this.editAttendeeRole.setSelectedIndex(2);
			break;
			
		case Author:
			this.editAttendeeRole.setSelectedIndex(3);
			break;
			
		case Customer:
			this.editAttendeeRole.setSelectedIndex(4);
			break;
		}
	}
	
	/**
	 * This is action for adding new attendees from the input form.
	 *
	 */
	private class AddNewAttendeeAction extends AbstractAction {
		private static final long serialVersionUID = -5311334473554149230L;
		@Override
		public void actionPerformed(ActionEvent e) {
			slideList.addToList(getAttendeeNewForm());
		}
	}
	
	private class EditAttendeeAction extends AbstractAction {
		private static final long serialVersionUID = 7440263362697642371L;
		@Override
		public void actionPerformed(ActionEvent e) {
			Attendee attendee = (Attendee)e.getSource();
			editAttendee = attendee;
			
			//save edited attendee
			/*
			editAttendee = new Attendee();
			editAttendee.setId(attendee.getId());
			editAttendee.setName(attendee.getName());
			editAttendee.setContact(attendee.getContact());
			editAttendee.setRole(attendee.getRole());
			editAttendee.setAspects(attendee.getAspects());
			*/
			
			slideList.startEdit(attendee);
			
			setEditForm(attendee);
			initFormPanel(editFormPanel);
			headingLabel.setCaption(
					Messages.getString("PearReview.Scribe.tabs.attendees") +
					" - " + Messages.getString(
					"PearReview.Moderator.attendees.edit_caption"), true);
		}
	}
	
	private class EndEditAttendeeAction extends AbstractAction {
		private static final long serialVersionUID = 7440263362697642371L;
		@Override
		public void actionPerformed(ActionEvent e) {
			
			slideList.endEdit(getAttendeeEditForm());
			initFormPanel(newFormPanel);
			headingLabel.setCaption(
					Messages.getString("PearReview.Scribe.tabs.attendees"),
					false);
		}
	}
	
	private class AbortEditAttendeeAction extends AbstractAction {
		private static final long serialVersionUID = -728084227566166606L;
		@Override
		public void actionPerformed(ActionEvent e) {
			
			slideList.abortEdit();
			initFormPanel(newFormPanel);
			headingLabel.setCaption(
					Messages.getString("PearReview.Scribe.tabs.attendees"),
					false);
		}
	}
	
	private class RemoveConfirmer implements Serializable,
			SlideBoxPanel.RemoveConfirmer {
		private static final long serialVersionUID = 4243556758179978388L;
		@Override
		public boolean canRemove(SlideBoxPanel<?> panel, Object element,
				int index) {
			if(element instanceof Attendee) {
				Attendee attendee = (Attendee) element;
				return canRemove(attendee);
			}
			return true;
		}
		private boolean canRemove(Attendee attendee) {
			// TODO attendee remove confirmer
			return true;
		}
	}

	@Override
	public String getHint() {
		return Messages.getString("PearReview.hint.moderator.attendees");
	}

	@Override
	public String getErrorMessage() {
		return Messages.getString("PearReview.Moderator.tabs.attendees_error");
	}

	@Override
	public void setNextViewAction(Action action) {
		bottom.setNextViewAction(action);
	}

	@Override
	public void setPreviousViewAction(Action action) {
		bottom.setPreviousViewAction(action);
	}
}